home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1997 July / macformat52.iso / mac / Shareware Plus / Educational / LEE 2.1 / Source / world.c < prev   
Text File  |  1996-07-29  |  10KB  |  432 lines

  1. /* world.c
  2.  *                         Copyright (1993)
  3.  *
  4.  *         Jeff Elman.  University of California, San Diego
  5.  *          Rik Belew.  University of California, San Diego
  6.  *      Stefano Nolfi.  Institute of Psychology, Rome.
  7.  *    Filippo Menczer.  University of California, San Diego
  8.  *        Greg Linden.  University of California, San Diego
  9.  *
  10.  *        This software may be redistributed without charge;
  11.  *                 this notice should be preserved.
  12.  */
  13.  
  14. #include "defs.h"
  15.  
  16.  
  17.  
  18.  
  19.  
  20. /*
  21.  * called in populati.c;
  22.  * the world is updated to insert the organism in its cell
  23.  */
  24. ins_org(ip)
  25.  
  26.     struct indiv *ip;
  27. {
  28.     cell *temp;
  29.  
  30.     temp = (cell *)malloc(sizeof(cell));
  31.     if (temp == (cell *) NIL_POINTER)
  32.     {
  33.         fprintf(stderr, "cell malloc error in ins_org()\n");
  34.         exit(-1);
  35.     }
  36.     temp->type = org;
  37.     temp->datum.ap = ip;
  38.     temp->next = world[ip->worldx][ip->worldy];
  39.     world[ip->worldx][ip->worldy] = temp;
  40.  
  41.     ins_org_Interactive(ip);
  42. }
  43.  
  44.  
  45.  
  46. /*
  47.  * the world is updated to insert a food element in a cell
  48.  */
  49. boolean ins_food(element, x, y, check)
  50.  
  51.     int element;
  52.     int x, y;
  53.     boolean check;
  54. {
  55.     cell    *temp, *temp1;
  56.  
  57.     temp = temp1 = world[x][y];
  58.     while (temp != (cell *)NIL_POINTER) {
  59.         if (check)
  60.           if (temp->type==food)
  61.             if (react_table[temp->datum.atom][element].possible)
  62.             return(FALSE);
  63.         temp1 = temp;
  64.         temp = temp->next;
  65.     }
  66.  
  67.     temp = (cell *)malloc(sizeof(cell));
  68.     if (temp == (cell *) NIL_POINTER)
  69.     {
  70.         fprintf(stderr, "cell malloc error in ins_food()\n");
  71.         exit(-1);
  72.     }
  73.     temp->type = food;
  74.     temp->datum.atom = element;
  75.     temp->next = (cell *)NIL_POINTER;
  76.     if (temp1 == (cell *)NIL_POINTER) world[x][y] = temp;
  77.     else temp1->next = temp;
  78.  
  79.     return(TRUE);
  80. }
  81.  
  82. /*
  83.  * called in populati.c;
  84.  * the world is updated to delete the organism from its cell
  85.  */
  86. del_org(ip)
  87.  
  88.     struct indiv *ip;
  89. {
  90.     cell *temp, *temp2;
  91.     boolean done = FALSE;
  92.     int    itemNum=0;
  93.     int    x,y;
  94.     
  95.     x = ip->worldx;
  96.     y = ip->worldy;
  97.  
  98.     temp = world[ip->worldx][ip->worldy];
  99.     if (temp == (cell *)NIL_POINTER)
  100.     {
  101.         printf("ERROR: can't find indiv to be deleted");
  102.         exit(1);
  103.     }
  104.     else if ((temp->type == org) && (temp->datum.ap == ip))
  105.     {
  106.         world[ip->worldx][ip->worldy] = temp->next;
  107.         free((char *) temp);
  108.         done = TRUE;
  109.     }
  110.     else while ((temp->next != (cell *)NIL_POINTER) && 
  111.             !((temp->next->type == org) && 
  112.               (temp->next->datum.ap == ip))) {
  113.             temp = temp->next;
  114.             itemNum++;
  115.     }
  116.     if (!done)
  117.     {
  118.         if (temp->next == (cell *)NIL_POINTER)
  119.         {
  120.             printf("ERROR: can't find indiv to be deleted");
  121.             exit(1);
  122.         }
  123.         else
  124.         {
  125.             temp2 = temp->next;
  126.             temp->next = temp2->next;
  127.             free((char *) temp2);
  128.         }
  129.     }
  130.  
  131.  
  132.     del_org_Interactive(x,y, itemNum);
  133. }
  134.  
  135.  
  136.  
  137.  
  138. /*
  139.  * called in populati.c;
  140.  * the world is filled with food elements of
  141.  * the various types according to their distribution
  142.  */
  143. init_world()
  144.  
  145. {
  146.     register int     x,y,i;
  147.     int        t;
  148.  
  149.     /*
  150.      * initialize world cells
  151.      */
  152.     for (x=0; x<x_dim; x++)
  153.        for (y=0; y<y_dim; y++)
  154.           world[x][y] = (cell *)NIL_POINTER;
  155.  
  156.     /*
  157.      * fill in cells with food elements
  158.      */
  159.     t = abundance * x_dim * y_dim;
  160.     for (i=0; i<t; i++) update_world();
  161. }
  162.  
  163.  
  164.  
  165. /* 
  166.  * called in populati.c;
  167.  * the world is replenished with new food elements
  168.  * to make up for the ones that have been consumed
  169.  */
  170. update_world()
  171.  
  172. {
  173.     int         t,i;
  174.     int         xpos, ypos;
  175.     int        counter;
  176.  
  177.  
  178.     for (t=0; t<types; t++)
  179.            if (0.5 + rans(0.5) < (float)distrib[t][4]/100.0)  
  180.            {
  181.  
  182.             /* Don't allow two reactable atoms in the
  183.                same cell.  */
  184.     
  185.             counter=0;
  186.             
  187.             do 
  188.             {
  189.                 if (counter>100) 
  190.                 {
  191.                     if(saturation) break;
  192.                     else
  193.                     {
  194.                         printf("Unable to place food \n(use the -S option to avoid trying to replenish a saturated world).\n");
  195.                         exit(1);
  196.                     }
  197.                 }
  198.     
  199.                 xpos = 0;
  200.                 ypos = 0;
  201.                 for (i=0; i<distrib[t][2]; i++)
  202.                    xpos += (mrand(x_dim)-(int)(x_dim/2));
  203.                 for (i=0; i<distrib[t][3]; i++)
  204.                    ypos += (mrand(y_dim)-(int)(y_dim/2));
  205.                 xpos /= distrib[t][2];
  206.                 ypos /= distrib[t][3];
  207.                 xpos += (x_dim+distrib[t][0]);
  208.                 ypos += (y_dim+distrib[t][1]);
  209.                 xpos %= x_dim;
  210.                 ypos %= y_dim;
  211.                 counter++;
  212.             } while (!(ins_food(t, xpos, ypos, TRUE)));
  213.             
  214.             update_world_Interactive(xpos, ypos);
  215.         }
  216. }
  217.  
  218.  
  219.  
  220.  
  221. /*      After digestion, the organism can only
  222.         retain gutSize number of atoms inside it.
  223.         Extra must be removed. */
  224.  
  225. int expel (organism)
  226.         struct indiv    *organism;
  227. {
  228.         int atoms_in_gut=0, counter, numExpelled = 0;
  229.  
  230.         for (counter=0; counter<types;counter++)
  231.                 atoms_in_gut+=organism->gut[counter];
  232.  
  233.         while (atoms_in_gut>organism->gutsize) {
  234.                 counter = mrand(types);
  235.                 if (organism->gut[counter]>0) {
  236.                         organism->gut[counter]--;
  237.                         ins_food(counter, organism->worldx, organism->worldy, FALSE);
  238.                         atoms_in_gut--;
  239.                         numExpelled++;
  240.                 }
  241.         }
  242.  
  243.         return(numExpelled);
  244. }
  245.  
  246.  
  247. /*
  248.  * u_digest() takes care of easy case when reactions
  249.  * are unary (-U option) rather than binary:
  250.  * all atomes reactive, no by-products...
  251.  */
  252. void u_digest (organism)
  253.         struct indiv    *organism;
  254. {
  255.     int x;
  256.     float calories = 0.0;
  257.  
  258.     for (x=0;x<types;x++)
  259.     {
  260.         calories += organism->gut[x] * react_table[x][0].energy;
  261.         organism->gut[x] = 0;
  262.         organism->energy += calories;
  263.     }
  264. }
  265.  
  266.  
  267. /*      digest() attemps to match the atoms in the
  268.         gut to get a reaction.  Any reaction can
  269.         produce new atoms which are still in
  270.         the gut and can produce secondary
  271.         reactions.  These reactions can cause
  272.         energy to be both added and subtracted from
  273.         the organism. */
  274.  
  275. void digest (organism)
  276.         struct indiv    *organism;
  277. {
  278.  
  279.         int     order[MAXTYPES], counter, x,y, swap;
  280.         boolean react;
  281.  
  282.         do {
  283.                 react = FALSE;
  284.  
  285.                 /* Randomly determine the order with which to check
  286.                 the reactions */
  287.                 for (counter=0;counter<types; counter++)
  288.                         order[counter] = counter;
  289.                 if (types>1) {
  290.                         for (counter = 0; counter<types*2; counter++)
  291. {
  292.                                 if (mrand(2) == 1) {
  293.                                         x = mrand(types);
  294.                                         do {
  295.                                                 y = mrand(types);
  296.                                         } while (y==x);
  297.                                         swap = order [x];
  298.                                         order[x] = order [y];
  299.                                         order[y] = swap;
  300.                                 }
  301.                         }
  302.                 }
  303.  
  304.                 for (x=0;x<types;x++)
  305.                         if (organism->gut[order[x]]>0)
  306.                                 for (y=0;y<=x;y++)
  307.                                         if (organism->gut[order[y]]>0)
  308.                                                if ((x!=y)||(organism->gut[order[x]]>1))
  309.                                                         react = reactAtoms(organism, order[x], order[y]);
  310.         } while (react);
  311. }
  312.  
  313.  
  314. /*      Used by digest().
  315.         If the atoms x and y can react, react
  316.         them, modify the energy of of the organism appropriately,
  317.         remove the atoms from the gut vector, add the byproducts,
  318.         and set react = TRUE */
  319.  
  320. boolean
  321. reactAtoms (organism, x, y)
  322.         struct indiv            *organism;
  323.         int                     x,y;
  324. {
  325.         int                     counter;
  326.  
  327.  
  328.         if (react_table[x][y].possible==FALSE)
  329.                 return(FALSE);
  330.         else {
  331.                 organism->gut[x]--;
  332.                 organism->gut[y]--;
  333.  
  334.                 for (counter=0; counter<types; counter++)
  335.                         organism->gut[counter] += react_table[x][y].by_prod[counter];
  336.  
  337.                 organism->energy+=react_table[x][y].energy;
  338.  
  339.                 return(TRUE);
  340.         }
  341. }
  342.  
  343.  
  344.  
  345.  
  346.  
  347. /*
  348.  * called by act_in_world() in gworld.c;
  349.  * all food-content of new cell position is put
  350.  * in the gut (may exceed gut_size);
  351.  * the world is updated (food removed)
  352.  * 
  353.  * NOTE: for now, organisms cannot eat each other
  354.  */
  355. ingest(ip)
  356.  
  357.     struct indiv *ip;
  358. {
  359.     cell        *t1, *t2;
  360.     int            numIngested=0;
  361.  
  362.     while (((t1 = world[ip->worldx][ip->worldy]) != 
  363.         (cell *)NIL_POINTER) && (t1->type == food))
  364.     {
  365.         ++(ip->gut[t1->datum.atom]);
  366.         numIngested++;
  367.         world[ip->worldx][ip->worldy] = t1->next;
  368.         free((char *) t1);
  369.     }
  370.     if ((t2 = t1) != (cell *)NIL_POINTER) 
  371.       if (t1->type == org)
  372.             while (t1->next != (cell *)NIL_POINTER)
  373.         {
  374.         t1 = t1->next;
  375.         if (t1->type == food)
  376.         {
  377.             ++(ip->gut[t1->datum.atom]);
  378.             numIngested++;
  379.             t2->next = t1->next;
  380.             free((char *) t1);
  381.             t1 = t2;
  382.         }
  383.  
  384.         else if (t1->type == org) 
  385.             t2 = t1;
  386.         else
  387.         {
  388.             printf("ERROR: unrecognized cell content\n");
  389.             exit(1);
  390.         }
  391.     }
  392.         
  393.     return(numIngested);        
  394. }
  395.  
  396.  
  397.  
  398. /*
  399.  * act_in_world() causes the organism to move
  400.  * and ingest food; if reactions are unary, all atoms
  401.  * are processes and there is no need to expel
  402.  */
  403.  
  404. float act_in_world (organism)
  405.         struct indiv            *organism;
  406. {
  407.         int     startX, startY, numExpelled=0;
  408.         float delta_en = organism->energy;
  409.  
  410.         startX = organism->worldx;
  411.         startY = organism->worldy;
  412.  
  413.         move(organism);
  414.         if (learn == 2) sense_world(organism);
  415.         ingest(organism);
  416.         if (unary_reactions) u_digest(organism);
  417.     else
  418.     { 
  419.         digest(organism);
  420.             numExpelled = expel(organism);
  421.     }
  422.  
  423.         actInWorldInteractive(organism, numExpelled, startX, startY);
  424.         
  425.         delta_en = organism->energy - delta_en;
  426.         return(delta_en);
  427.  
  428. }
  429.  
  430.  
  431.  
  432.